在介紹本篇我們先來複習一下先前在 pure function 那章提過的一些名詞
但在現實開發中則無法避免這些 Side Effect 的操作,舉幾個例子,
localStorage,console,new Date),Math.random),所以今天就要講講在 Functional Programming 中,如何去處理這些 side effect
example
在還沒開始介紹 IO 前,先來看看原本我們是如何寫出 pure function, 沒錯,就是 dependency injection.
假設現在有一個函式,其功用是要取得 document.body 的高度,
function getBodyOffsetHeight() {
return document.querySelector('body').offsetHeight;
}
const offSetHeight = getBodyOffsetHeight();
可以看到 getBodyOffsetHeight 是一個 impure function,因為 DOM 有可能隨時改變,會使得每次呼叫 getBodyOffsetHeight 結果有可能會不一樣,要如何把它變成 pure function 呢?
function getBodyOffsetHeightFromDOM($) {
return $('body').offsetHeight;
}
const qs = document.querySelector.bind(document);
const offSetHeight = getBodyOffsetHeightFromDOM(qs);
沒錯,可以直接把 document 直接當參數進行傳入,這樣就可以確保給定一樣的輸入就會有得到相同的輸出,這樣不就是一個 pure function 了嘛!!
advantage
這種方法的好處是讓我們在進行 unit test 時,可以不用模擬一個專門測試的 DOM (ex: JSDOM),也就是讓程式可可測試性增加。
const mockQS = () => ({ offsetHeight: 1000 });
const offSetHeight = getUserNameFromDOM(mockQS);
assert.strictEqual(offSetHeight, 1000, true)
disadvantage
雖然我們確保了函式是 pure function 跟可測試,但當我們是開發一個大型的 App,則導致 App 非常難以維護及閱讀。
舉例來說,由於函式要 pure, 所以我們在最外層的 function 注入所有需要的的 dependency,但如果這個函式裡面是非常深層的,就必須要將參數不斷傳遞,這將會導致我們的程式碼非常難以維護。
const App = ($, localStorage, date, config, ... ) => {
/** prop drilling */
}
今天因為考駕照太忙了,
所以將原訂計畫稍加更改,明天將來介紹 IO Monad 是如何處理 Side Effect 的!
感謝大家閱讀!
NEXT: Handle Side Effect - IO Monad